package com.javatip.project.detection.detectionDataset.controller;

import java.io.File;
import java.util.*;

import com.alibaba.fastjson.JSON;
import com.javatip.common.constant.IsPublic;
import com.javatip.common.utils.ImageResizer;
import com.javatip.common.utils.file.FileUtils;
import com.javatip.common.utils.security.ShiroUtils;
import com.javatip.project.Controller.getUserInfo.controller.GetUserRoleController;
import com.javatip.project.system.user.service.IUserService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.*;
import com.javatip.project.detection.detectionDataset.domain.DetectionDataset;
import com.javatip.project.detection.detectionDataset.service.IDetectionDatasetService;
import com.javatip.framework.web.controller.BaseController;
import com.javatip.framework.web.page.TableDataInfo;
import com.javatip.framework.web.domain.AjaxResult;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;

/**
 * 目标检测数据集信息操作处理
 *
 * @author 袁伟
 * @date 2024-09-22
 */
@Api(tags = "目标检测数据集管理")
@Controller
@RequestMapping("/detection/detectionDataset")
public class DetectionDatasetController extends BaseController {
    private String prefix = "detection/detectionDataset";

    @Autowired
    private IDetectionDatasetService detectionDatasetService;

    @Autowired
    private IUserService userService;

    @Autowired
    GetUserRoleController getUserRoleController;

    @RequiresPermissions("detection:detectionDataset:view")
    @GetMapping()
    public String detectionDataset() {
        return prefix + "/detectionDataset";
    }

    /**
     * 查询目标检测数据集列表
     */
    @RequiresPermissions("detection:detectionDataset:list")
    @PostMapping("/list")
    @ResponseBody
    @ApiOperation(value = "获取所有目标检测数据集")
    public TableDataInfo list(@RequestParam(value = "userId", required = false) Integer userId, DetectionDataset detectionDataset) {
        startPage();
        if (userId != null) {
//            System.out.println("userId = " + userId);
            List<DetectionDataset> list = detectionDatasetService.selectDetectionDatasetList(detectionDataset);
            List<DetectionDataset> resultList = new ArrayList<>();
            for (DetectionDataset dataset : list) {
                if (dataset.getUserId() == userId) {
                    resultList.add(dataset);
                }
            }
            for (DetectionDataset dataset : resultList) {
                dataset.setUserName(userService.selectUserById(Long.valueOf(dataset.getUserId())).getUserName());
            }
            return getDataTable(resultList);
        } else {
            List<DetectionDataset> list = detectionDatasetService.selectDetectionDatasetList(detectionDataset);
            // 判断是否是管理员
            if (getUserRoleController.isAdmin().getBody()) {
                return getDataTable(list);
            } else {
                // 只返回自己的和公开的数据集
                List<DetectionDataset> resultList = new ArrayList<>();
                for (DetectionDataset dataset : list) {
                    if (dataset.getIsPublic() == IsPublic.PUBLIC || dataset.getUserId().equals(getUserRoleController.getUserId().getBody())) {
                        resultList.add(dataset);
                    }
                }
                return getDataTable(resultList);

            }
        }
    }

    @GetMapping("/getDatasetList")
    @ResponseBody
    @ApiOperation(value = "获取数据集列表")
    public AjaxResult getDatasetList() {
        int currentUserId = ShiroUtils.getSysUser().getUserId().intValue();
        List<DetectionDataset> list = detectionDatasetService.selectDetectionDatasetList(new DetectionDataset());

        List<Map<String, Object>> datasetList = new ArrayList<>();
        for (DetectionDataset dataset : list) {
            if (dataset.getUserId() == currentUserId || dataset.getIsPublic() == IsPublic.PUBLIC) {
                Map<String, Object> datasetInfo = new HashMap<>();
                datasetInfo.put("id", dataset.getId()); // 添加id
                datasetInfo.put("name", dataset.getName()); // 添加数据集名称
                datasetInfo.put("userName",  userService.selectUserById(Long.valueOf(dataset.getUserId())).getUserName());
                datasetInfo.put("numTrain", dataset.getNumTrain()); // 添加训练集数量
                datasetInfo.put("numVal", dataset.getNumVal()); // 添加验证集数量
                datasetInfo.put("uploadTime", dataset.getUploadTime()); // 添加上传时间
                datasetInfo.put("userId", dataset.getUserId());
                datasetInfo.put("location", dataset.getLocation());
                datasetInfo.put("isPublic", dataset.getIsPublic());
                datasetList.add(datasetInfo);
            }
        }
        return AjaxResult.success(JSON.toJSONString(datasetList));
    }


    /**
     * 新增目标检测数据集
     */
    @GetMapping("/add")
    public String add() {
        return prefix + "/add";
    }

    /**
     * 新增保存目标检测数据集
     */
    @RequiresPermissions("detection:detectionDataset:add")
    @PostMapping("/add")
    @ResponseBody
    public AjaxResult addSave(DetectionDataset detectionDataset) {
        return toAjax(detectionDatasetService.insertDetectionDataset(detectionDataset));
    }

    /**
     * 修改目标检测数据集
     */
    @GetMapping("/edit/{id}")
    public String edit(@PathVariable("id") Integer id, ModelMap mmap) {
        DetectionDataset detectionDataset = detectionDatasetService.selectDetectionDatasetById(id);
        mmap.put("detectionDataset", detectionDataset);
        return prefix + "/edit";
    }

    /**
     * 修改保存目标检测数据集
     */
    @RequiresPermissions("detection:detectionDataset:edit")
    @PostMapping("/edit")
    @ResponseBody
    public AjaxResult editSave(DetectionDataset detectionDataset) {
        return toAjax(detectionDatasetService.updateDetectionDataset(detectionDataset));
    }

    /**
     * 删除目标检测数据集
     */
    @RequiresPermissions("detection:detectionDataset:remove")
    @PostMapping("/remove")
    @ResponseBody
    public AjaxResult remove(String ids) {
        return toAjax(detectionDatasetService.deleteDetectionDatasetByIds(ids));
    }

    @ApiOperation(value = "检测数据集名称是否存在")
    @GetMapping("/checkName")
    @ResponseBody
    public boolean checkName(@RequestParam(value = "name") String datasetName) {
        System.out.println("datasetName = " + datasetName);
        return false;
    }


    @ApiOperation(value = "上传数据集")
    @PostMapping("/uploadDataset")
    @ResponseBody
// 前端传formData数据，后端接收并处理
    public AjaxResult uploadDataset(MultipartHttpServletRequest request) {

        // 显示前端传来的formData数据
        List<MultipartFile> image = request.getFiles("image-upload");
        List<MultipartFile> label = request.getFiles("label-upload");
        String datasetName = request.getParameter("datasetName");
        int currentUserId = Math.toIntExact(ShiroUtils.getSysUser().getUserId());
        String destinationPath = System.getProperty("user.dir") + "/src/main/resources/detectionDataset/" + String.valueOf(currentUserId);
//        获取是否公开
        int isPublic = Integer.parseInt(request.getParameter("isPublic"));

        // 根据用户id和数据集名称查询数据集
        DetectionDataset detectionDataset = detectionDatasetService.selectDetectionDatasetByName(datasetName, currentUserId);

        //处理上传文件
        if (image != null && !image.isEmpty()
                && datasetName != null && !datasetName.isEmpty()) {
            try {
                File destinationDir = new File(destinationPath, datasetName); // 创建文件夹路径
                if (!destinationDir.exists()) {
                    destinationDir.mkdirs(); // 创建文件夹
                }

                File trainImageDir = new File(destinationDir, "images"); // 创建image文件夹路径
                if (!trainImageDir.exists()) {
                    trainImageDir.mkdirs(); // 创建image文件夹
                }

                File trainLabelDir = new File(destinationDir, "labels"); // 创建label文件夹路径
                if (!trainLabelDir.exists()) {
                    trainLabelDir.mkdirs(); // 创建label文件夹
                }

                for (MultipartFile file : image) {
                    // 保存文件到指定位置
                    file.transferTo(new File(trainImageDir, file.getOriginalFilename())); // 复制文件到image文件夹
                }

                for (MultipartFile file : label) {
                    // 保存文件到指定位置
                    file.transferTo(new File(trainLabelDir, file.getOriginalFilename())); // 复制文件到label文件夹}
                }

                if (detectionDataset == null) {
                    detectionDataset = new DetectionDataset();
                    detectionDataset.setName(datasetName);
                    detectionDataset.setNumTrain(image.size());
                    detectionDataset.setNumVal(label.size());
                    detectionDataset.setUserId(currentUserId);
                    //上传时间设置为当前时间
                    detectionDataset.setUploadTime(new Date());
                    detectionDataset.setIsPublic(isPublic);
                    detectionDataset.setLocation(destinationPath + "/" + datasetName + "/"); // 设置路径
                    detectionDataset.setHeight(Integer.parseInt(request.getParameter("height")));
                    detectionDataset.setWidth(Integer.parseInt(request.getParameter("width")));
                    //默认不公开
                    detectionDataset.setIsPublic(IsPublic.NOT_PUBLIC);
//                    获取是否公开
                    if (isPublic == 1) {
                        detectionDataset.setIsPublic(IsPublic.PUBLIC);
                    } else {
                        detectionDataset.setIsPublic(IsPublic.NOT_PUBLIC);
                    }
                    System.out.println("新增数据集信息" + detectionDataset);
                    detectionDatasetService.insertDetectionDataset(detectionDataset);
                } else {
                    System.out.println("更新数据集信息");
//                    dataset.setName(datasetName);
                    detectionDataset.setNumTrain(image.size());
                    detectionDataset.setNumVal(label.size());
//                    dataset.setUserId(currentUserId);
                    //上传时间设置为当前时间
                    detectionDataset.setUploadTime(new Date());
                    detectionDataset.setHeight(Integer.parseInt(request.getParameter("height")));
                    detectionDataset.setWidth(Integer.parseInt(request.getParameter("width")));
                    detectionDatasetService.updateDetectionDataset(detectionDataset);
                }
                // 启动新线程执行异步任务
                new Thread(() -> {
                    try {
                        System.out.println("destinationPath:" + destinationPath);
                        // 耗时操作，譬如 ImageResizer
                        ImageResizer.resizeAndConvertImages(destinationPath + "/" + datasetName + "/",
                                Integer.parseInt(request.getParameter("height")),
                                Integer.parseInt(request.getParameter("width")));
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }).start();
                return AjaxResult.success("文件上传成功");
            } catch (Exception e) {
                e.printStackTrace();
                return AjaxResult.error("文件上传失败");
            }
        } else {
            return AjaxResult.error("未选择文件或文件夹名为空");
        }
    }

    @ApiOperation(value = "删除数据集")
    @PostMapping("/delete")
    @ResponseBody
    public AjaxResult deleteDataset(@RequestBody Map<String, Integer> params) {
        Integer id = params.get("id");
        DetectionDataset detectionDataset = detectionDatasetService.selectDetectionDatasetById(id);
        if (detectionDataset != null) {
            String datasetPath = detectionDataset.getLocation();
            try {
                // 删除数据集文件夹
                File file = new File(datasetPath);
                if (file.exists()) {
                    FileUtils.deleteFolderFile(String.valueOf(file));
                }
                return AjaxResult.success("删除成功");
            } catch (Exception e) {
                e.printStackTrace();
                return AjaxResult.error("删除失败");
            }
        } else {
            return AjaxResult.error("数据集不存在");
        }
    }

    @ResponseBody
    @PostMapping("/resizePicture")
    public void resizePicture(int id, int height, int width) {
        DetectionDataset detectionDataset = detectionDatasetService.selectDetectionDatasetById(id);
        String location = detectionDataset.getLocation();
        System.out.println("location: " + location);
        System.out.println("height: " + height);
        System.out.println("width: " + width);
        ImageResizer.resizeAndConvertImages(location, height, width);
    }

    @GetMapping("/getImages")
    @ResponseBody
    public List<String> getImages(@RequestParam String path) {
//        System.out.println("path: " + path);
        // 获取图片文件列表
        List<String> imageList = new ArrayList<>();
        File file = new File(path);
        if (file.exists()) {
            for (File imageFile : file.listFiles()) {
                if (imageFile.isFile() && imageFile.getName().endsWith(".jpg")) {
                    imageList.add(imageFile.getName());
//                    System.out.println("imageFile: " + imageFile.getName());
                }
            }
//            System.out.println("imageList: " + imageList);
            return imageList;
        }
        System.out.println("路径不存在");
        return null;

    }

    @GetMapping("/getLabels")
    @ResponseBody
    public List<String> getLabels(@RequestParam String path) {
//        System.out.println("path: " + path);
        // 获取标签文件列表
        List<String> labelList = new ArrayList<>();
        File file = new File(path);
        if (file.exists()) {
            for (File labelFile : file.listFiles()) {
                if (labelFile.isFile() && labelFile.getName().endsWith(".txt")) {
                    labelList.add(labelFile.getName());
                }
            }
            return labelList;
        }
        return null;
    }

}
